/* 这个组件包括三类表单输入：
    1.交易币种转换: 它的值使用 addMinus 中的 validateForms 来控制；
    2.机构密钥配置: 它的值使用 [ngModel] 和 (ngModalChange) 来控制
    3.商户功能配置: 它的值使用 this.validateForm 来控制；
 */
import { Component, OnInit, ViewChild, ElementRef } from '@angular/core'
import { FormBuilder, Validators, AbstractControl, FormControl, FormGroup } from '@angular/forms'
import uuid from 'uuid'
import { BehaviorSubject, of, Observable } from 'rxjs'
import { NzMessageService } from 'ng-zorro-antd'
import { switchMap, mergeMap, map, tap } from 'rxjs/operators'

import { AcquirerNewBaseClass } from '../baseClass'
import { AcquirerStoreService } from '../acquirer-store.service'
import { ExchangeRate, AccessMode, Access, IExchangeRateInput } from '@shared/interfaces/acquirer'
import { AddMinusService } from '@shared/services/addMinus.service'
import { CurrencyService } from '@shared/services/currency.service'
import {
  transExchangeRateToOptions,
  compareTwoCurrencies,
  makeAllControlDirty,
  getIntLengthOfFloat,
  parseSelRate,
  numScale,
} from 'app/utils/helpers'
import { PublicService } from '@shared/services/public.service'
import { IExchangeRateQueryParams, ICurrencyOption } from '@shared/interfaces/common'
import { alphanumericReg, positiveReg, twoDecimalReg, customTradeSelRateLength } from 'app/utils/contraints'
import { PageService } from '@shared/services/page.service'
import { currencyConvertUniqueValidator } from 'app/utils/form-control.validator'
import { I18NService } from '@core'

enum ERateSponsor {
  BEST = 'BEST',
  JCB = 'JCB',
  MCI = 'MCI',
  UPI = 'UPI',
  FIXED = 'FIXED',
}

@Component({
  selector: 'app-acquirer-new-trade',
  templateUrl: './trade.component.html',
  providers: [AddMinusService],
  styleUrls: ['./trade.component.less'],
})
export class AcquirerNewTradeComponent extends AcquirerNewBaseClass implements OnInit {
  /*************************************** 交易币种转换功能 ***********************************/
  private _sourceCurrencyOptions$ = new BehaviorSubject([]) // 商户交易币种选项
  private _currencyOptions$ = new BehaviorSubject([]) // 币种选项

  exchangeOptions = [
    { label: this.trans('BIZ.ACQUIRER.OTHER.TRADE.BEST_RATE'), value: 'BEST' },
    { label: 'JCB', value: 'JCB' },
    { label: 'MCI', value: 'MCI' },
    { label: 'UPI', value: 'UPI' },
    { label: this.trans('BIZ.ACQUIRER.OTHER.TRADE.FIXED_RATE'), value: 'FIXED' },
  ]

  sourceCurrencyOptionsObs = this._sourceCurrencyOptions$.asObservable()
  currencyOptionsObs = this._currencyOptions$.asObservable()

  sourceCurrencyOptionsObsArray: Observable<ICurrencyOption[]>[] = [] // 商户交易币种也会改变
  currencyOptionsObsArray: Observable<ICurrencyOption[]>[] = [] // 因为可以有多个币种转换，每个都需要不同的事件流去维护，所以是数组
  selRateOptionsObsArray: Observable<any[]>[] = [] // 同上

  searchValueArray: BehaviorSubject<string>[] = []
  searchValue$ = new BehaviorSubject<string>('')

  // isExchangeRateDisabled = true
  isExchangeRateDisabledArray: boolean[] = []
  selRateOptions = [] // 转换汇率选项
  bestSelRateArray: number[] = [] // 最优项数组
  chosenExchange: Array<IExchangeRateInput> = [] // sellRate 可以选择也可以输入，
  compareCurrencyFn = compareTwoCurrencies

  errorTips = {}

  /*************************************** 机构密钥配置功能 ***********************************/
  @ViewChild('acquirerAccessInput') acquirerAccessInput: ElementRef
  @ViewChild('nodeAccessInput') nodeAccessInput: ElementRef

  accessValidateForm: FormGroup // 表单校验
  accessErrorTips: { [key: string]: {} } // 错误提示
  accessModeEnum = AccessMode // 接入模式
  isMerchantAccess = false // 是否开启商户接入模式
  isAcquirerAccess$ = new BehaviorSubject<boolean>(false) // 是否开启收单系统接入模式
  isNodeAccess$ = new BehaviorSubject<boolean>(false) // 是否开启节点接入模式
  acquirerAccessKey: string
  nodeAccessKey: string

  isMerchantAccessDisEditable = new BehaviorSubject<boolean>(false)
  isAcquirerAccessDisEditable = false
  isNodeAccessDisEditable = false

  /*************************************** 商户功能 *****************************************/
  constructor(
    public fb: FormBuilder,
    public acquirerStore: AcquirerStoreService,
    public addMinusService: AddMinusService,
    public currencyService: CurrencyService,
    public publicService: PublicService,
    public msg: NzMessageService,
    public pageService: PageService,
    private i18n: I18NService,
  ) {
    super(fb, acquirerStore)
  }

  ngOnInit() {
    this.initCurrencyFunc()
    this.initAccessFunc()
    this.initMerFunc()
  }

  /*************************************** 交易币种转换功能 ***********************************/
  initCurrencyFunc(): void {
    this.initErrorTips()
    this.unsetInitOne()
    this.initAddMinus()
    this.initEventListener()
    this.initCurrencySelect()
    this.initSourceCurrencySelect()
    this.initSellRateSelect()
    this.addMinusService.eventEmitter.on('add', this.afterAddItem.bind(this))
  }

  afterAddItem(): void {
    this.initCurrencySelect()
    this.initSourceCurrencySelect()
  }

  /* 商户交易币种变化时 */
  srcCurrencyChange(index: number, currencyCode: string): void {
    if (!currencyCode) return
    this.removeSrcCurrencyInDstOptions(index, currencyCode)
    this.refreshExchangeRateSelect(index)
  }

  /* 转换交易币种变化时 */
  dstCurrencyChange(index: number, currencyCode: string): void {
    if (!currencyCode) return
    this.removeDstOptionsInSrcCurrency(index, currencyCode)
    this.refreshExchangeRateSelect(index)
  }

  /** 商户交易币种选择后，需要将其在转换币种选项中删除，因为需求中，不允许两个相同的币种进行转换 */
  removeSrcCurrencyInDstOptions(index: number, currencyCode: string): void {
    this.currencyOptionsObsArray[index] = this.currencyOptionsObsArray[index].pipe(
      switchMap(options => of(options.filter(option => option.value.code !== currencyCode))),
    )
  }

  /** 转换币种选择后，需要将其在商户交易币种中删除 */
  removeDstOptionsInSrcCurrency(index: number, currencyCode: string): void {
    this.sourceCurrencyOptionsObsArray[index] = this.sourceCurrencyOptionsObs.pipe(
      switchMap(options => of(options.filter(option => option.value.code !== currencyCode))),
    )
  }

  /* 刷新转化汇率选择器 */
  refreshExchangeRateSelect(index: number): void {
    this.refreshRateOptions(index)
  }

  /* 选择一个汇率 */
  chooseExchangeRate(index: number, rateSponsor: ERateSponsor): void {
    if (!rateSponsor) return
    this.selRateOptionsObsArray[index].subscribe(options =>
      this.handleSelRateOptionChosen(options, index, rateSponsor),
    )
  }

  handleSelRateOptionChosen(
    options: any,
    index: number,
    rateSponsor: ERateSponsor,
    existedSelRate?: ExchangeRate,
  ): void {
    this.isExchangeRateDisabledArray[index] = true
    if (options.length === 0) return
    const bestSelRate = options.reduce((old, o) => (o.value.selRate > old.value.selRate ? o : old)).value.selRate
    this.bestSelRateArray[index] = bestSelRate
    switch (rateSponsor) {
      case ERateSponsor.BEST:
        this.chosenExchange[index] = {
          isBest: true,
          selRate: bestSelRate,
        }
        return
      case ERateSponsor.JCB:
        this.chosenExchange[index] = {
          selRate: options.find(o => o.label === ERateSponsor.JCB).value.selRate,
          rateSponsor: ERateSponsor.JCB,
        }
        return
      case ERateSponsor.MCI:
        this.chosenExchange[index] = {
          selRate: options.find(o => o.label === ERateSponsor.MCI).value.selRate,
          rateSponsor: ERateSponsor.MCI,
        }
        return
      case ERateSponsor.UPI:
        this.chosenExchange[index] = {
          selRate: options.find(o => o.label === ERateSponsor.UPI).value.selRate,
          rateSponsor: ERateSponsor.UPI,
        }
        return
      case ERateSponsor.FIXED:
        this.isExchangeRateDisabledArray[index] = false
        this.chosenExchange[index] = {
          selRate: !!existedSelRate ? parseSelRate(existedSelRate.selRate) : 0,
          isFixed: true,
        }
        this.isExchangeRateDisabledArray[index] = false
        return
    }
  }

  searchCurrency(index: number, value: string): void {
    this.searchValueArray[index].next(value)
  }

  searchSourceCurrency(index: number, value: string): void {
    this.sourceCurrencyOptionsObsArray[index] = this.sourceCurrencyOptionsObs.pipe(
      switchMap(options => {
        const pattern = new RegExp(value, 'i')
        const filterOptions = options.filter(cur => {
          return pattern.test(cur.label) || pattern.test(cur.value.name)
        })
        return of(filterOptions)
      }),
    )
  }

  /** 输入自定义selRate */
  editCustomSelRate(value, index: number) {
    this.selRateValidator(value, this.addMinusService.validateForms[index].get('selRate'))
    this.chosenExchange[index].selRate = value
  }

  /** 自定义校验 */
  selRateValidator(value: number | string, control: AbstractControl) {
    /** 有效数字位数 8 位 */
    this.addMinusService.validateForms.forEach(form => makeAllControlDirty(form))
    const selRate = String(value)
    if (!positiveReg.test(selRate)) {
      control.setErrors({ pattern: true })
      return
    }
    if (selRate.replace('.', '').length > 8) {
      control.setErrors({ maxlength: true })
      return
    }
    control.setErrors(null)
  }

  /** 每次校验需要去刷新一下 selRate 校验 */
  refreshSelRateValidate() {
    this.addMinusService.validateForms.forEach((form, index) => {
      const exchange = this.chosenExchange[index]
      if (!exchange) return
      const { isFixed, selRate } = exchange
      if (!isFixed) return
      this.selRateValidator(selRate, form.get('selRate'))
    })
  }

  trans(key: string, params?: Object): string {
    return this.i18n.fanyi(key, params)
  }

  private refreshRateOptions(index: number, chosenRate?: ExchangeRate): void {
    const value = this.addMinusService.validateForms[index].value
    const params: IExchangeRateQueryParams = {
      dstCurrency: value.dstCurrency ? value.dstCurrency : null,
      srcCurrency: value.srcCurrency ? value.srcCurrency : null,
    }

    this.selRateOptionsObsArray[index] = this.publicService.getExchangeRate(params).pipe(
      mergeMap(exchangeRate => of(transExchangeRateToOptions(exchangeRate))),
      tap(options => {
        if (options.length === 0) {
          /** 得到非法的币种转换, 清空所有输入 */
          this.removeAllInput(index)
        }
      }),
    )

    const rateSponsor = this.getValidateFormValue(index, 'selRate')
    /** 当两个币种都有值时，发请求 */
    if (this.getValidateFormValue(index, 'srcCurrency') && this.getValidateFormValue(index, 'dstCurrency')) {
      this.selRateOptionsObsArray[index].subscribe(options => {
        this.handleSelRateOptionChosen(options, index, rateSponsor, chosenRate)
      })
    }
  }

  private removeAllInput(index: number): void {
    this.clearSrcCurrencySelect(index)
    this.clearDstCurrencySelect(index)
    this.clearSelRateSelect(index)
    this.clearSelRateInput(index)
    this.clearMarkUpInput(index)
  }

  private clearSrcCurrencySelect(index: number): void {
    this.setValidateFormValue(index, 'srcCurrency', null)
  }

  private clearDstCurrencySelect(index: number): void {
    this.setValidateFormValue(index, 'dstCurrency', null)
  }

  private clearSelRateSelect(index: number): void {
    this.setValidateFormValue(index, 'selRate', null)
  }

  private clearSelRateInput(index: number): void {
    this.chosenExchange[index].selRate = null
  }

  private clearMarkUpInput(index: number): void {
    this.setValidateFormValue(index, 'markup', null)
  }

  private getValidateFormValue(index: number, key: string): any {
    return this.addMinusService.validateForms[index].get(key).value
  }

  private setValidateFormValue(index: number, key: string, value: string | null): void {
    this.addMinusService.validateForms[index].get(key).setValue(value)
  }

  private initErrorTips(): void {
    this.errorTips = {
      srcCurrency: {
        required: this.trans('VALIDATION.REQUIRED_SELECT', {
          name: this.trans('BIZ.ACQUIRER.OTHER.TRADE.MERCHANT_CURRENCY'),
        }),
        existCurrConvert: this.trans('VALIDATION.CODE_EXISTS', {
          name: this.trans('BIZ.ACQUIRER.OTHER.CURRENCY_CONVERSION'),
        }),
      },
      dstCurrency: {
        required: this.trans('VALIDATION.REQUIRED_SELECT', {
          name: this.trans('BIZ.ACQUIRER.OTHER.TRADE.CHANNEL_CURRENCY'),
        }),
        existCurrConvert: this.trans('VALIDATION.CODE_EXISTS', {
          name: this.trans('BIZ.ACQUIRER.OTHER.CURRENCY_CONVERSION'),
        }),
      },
      markup: {
        required: this.trans('VALIDATION.REQUIRED', { name: 'mark up' }),
        min: this.trans('VALIDATION.MIN_VALUE', { value: '0' }),
        max: this.trans('VALIDATION.MAX_VALUE', { value: '10%' }),
        pattern: this.trans('VALIDATION.PATTERN.DECIMAL_PLACES', { place: 2 }),
      },
      selRate: {
        required: this.trans('VALIDATION.REQUIRED_SELECT', {
          name: this.trans('BIZ.ACQUIRER.OTHER.TRADE.CONVERT_RATE'),
        }),
        maxlength: this.trans('VALIDATION.MAX_LENGTH', { length: 8 }),
        pattern: this.trans('VALIDATION.PATTERN.VALID_NUMBER'),
      },
    }
  }

  /** addMinusService 首次不出现 */
  private unsetInitOne(): void {
    this.addMinusService.isInitOne = false
  }

  // 将校验方法、实例、已有的数据传给 addMinus service
  private initAddMinus(): void {
    const exchangeRates = this.acquirer.institution.common.tradeInfo.exchangeRates || []
    const generateFunc = exchange => {
      const { srcCurrency, dstCurrency, markup } = exchange
      const getParsedSelRateLabel = (ex: ExchangeRate) => {
        const { isBest, isFixed, rateSponsor } = ex
        if (isBest) {
          return 'BEST'
        }
        if (isFixed) {
          return 'FIXED'
        }
        return rateSponsor
      }
      return [
        {
          srcCurrency: new FormControl(srcCurrency, {
            validators: [Validators.required],
            asyncValidators: [
              currencyConvertUniqueValidator(this.addMinusService.validateForms, 'srcCurrency', 'dstCurrency'),
            ],
          }),
          dstCurrency: new FormControl(dstCurrency, {
            validators: [Validators.required],
            asyncValidators: [
              currencyConvertUniqueValidator(this.addMinusService.validateForms, 'dstCurrency', 'srcCurrency'),
            ],
          }),
          selRate: [
            !!exchange.selRate || exchange.selRate === 0 ? getParsedSelRateLabel(exchange) : null,
            [Validators.required],
          ],
          markup: [
            markup ? numScale(markup, 2) : null,
            [Validators.required, Validators.min(0), Validators.max(10), Validators.pattern(twoDecimalReg)],
          ],
        },
      ]
    }
    this.addMinusService.init(generateFunc, new ExchangeRate(), exchangeRates)
  }

  /** 初始化事件监听 */
  private initEventListener(): void {
    this.addMinusService.minusEvent$.subscribe((index: number) => {
      this.chosenExchange.splice(index, 1)
    })
  }

  /** 初始化商户交易币种 */
  private initSourceCurrencySelect(): void {
    this.initSourceCurrencyOptionsObs()
    const validateForms = this.addMinusService.validateForms
    this.sourceCurrencyOptionsObsArray = []
    validateForms.forEach(() => {
      this.sourceCurrencyOptionsObsArray.push(this.sourceCurrencyOptionsObs)
    })
  }

  private initSourceCurrencyOptionsObs(): void {
    this.sourceCurrencyOptionsObs = this.currencyService.getCurrencyOptions().pipe(
      switchMap(options => {
        return of(
          options.filter(option => {
            return this.acquirer.institution.common.currencies
              .map(currency => currency.code)
              .includes(option.value.code)
          }),
        )
      }),
    )
  }

  /* 初始化转化币种选择器 */
  private initCurrencySelect(): void {
    const exchangeRates = this.acquirer.institution.common.tradeInfo.exchangeRates || []
    const validateForms = this.addMinusService.validateForms
    this.currencyOptionsObsArray = []
    this.searchValueArray = []
    validateForms.forEach((form, index) => {
      const searchValue$ = new BehaviorSubject<string>('')
      const options$ = searchValue$.asObservable().pipe(
        switchMap(value => {
          return this.currencyService.getCurrencyOptions().pipe(map(options => this.filterMethod(options, value)))
        }),
      )

      this.currencyOptionsObsArray.push(options$)
      this.searchValueArray.push(searchValue$)
      if (exchangeRates[index]) {
        this.removeSrcCurrencyInDstOptions(index, exchangeRates[index].srcCurrency)
      }
    })
  }

  private filterMethod(options: ICurrencyOption[], value: string): ICurrencyOption[] {
    const pattern = new RegExp(value, 'i')
    return options.filter(cur => {
      return pattern.test(cur.label) || pattern.test(cur.value.code) || pattern.test(cur.value.number)
    })
  }

  /* 初始化转换汇率选择器 */
  private initSellRateSelect(): void {
    const { exchangeRates } = this.acquirer.institution.common.tradeInfo
    if (!exchangeRates) {
      return
    }
    exchangeRates.forEach((rate, i) => {
      this.refreshRateOptions(i, rate)
    })
  }

  /*************************************** 机构密钥配置功能 ***********************************/
  initAccessFunc(): void {
    this.initAccess()
    this.initAccessValidateForm()
    this.initAccessErrorTips()
  }

  /* 初始化接入模式 */
  initAccess(): void {
    const access = this.acquirer.institution.common.tradeInfo.access || []
    access.forEach(accessItem => {
      switch (accessItem.mode) {
        case AccessMode.Merchant:
          this.isMerchantAccess = true
          this.isMerchantAccessDisEditable.next(true && this.pageService.isTradeEdit)
          break
        case AccessMode.Acquirer:
          if (!accessItem.key) {
            break
          }
          this.isAcquirerAccess$.next(true)
          this.isAcquirerAccessDisEditable = true && this.pageService.isTradeEdit
          this.acquirerAccessKey = accessItem.key
          break
        case AccessMode.Node:
          if (!accessItem.key) {
            break
          }
          this.isNodeAccess$.next(true)
          this.isNodeAccessDisEditable = true && this.pageService.isTradeEdit
          this.nodeAccessKey = accessItem.key
          break
        default:
          console.error('初始化接入模式错误')
      }
    })
    if (!this.pageService.isTradeEdit) {
      this.isMerchantAccess = true
    }
  }

  initAccessValidateForm(): void {
    this.accessValidateForm = this.fb.group({
      acquirerAccessKey: new FormControl(
        {
          value: this.acquirerAccessKey,
          disabled: this.isAcquirerAccessDisEditable,
        },
        [Validators.required, Validators.pattern(alphanumericReg), Validators.maxLength(32), Validators.minLength(32)],
      ),
      nodeAccessKey: new FormControl(
        {
          value: this.nodeAccessKey,
          disabled: this.isNodeAccessDisEditable,
        },
        [Validators.required, Validators.pattern(alphanumericReg), Validators.maxLength(16), Validators.minLength(16)],
      ),
    })
  }

  initAccessErrorTips(): void {
    this.errorTips = {
      ...this.errorTips,
      acquirerAccessKey: {
        required: this.trans('VALIDATION.REQUIRED', { name: '' }),
        pattern: this.trans('VALIDATION.PATTERN.ALPHANUMERIC_ONLY'),
        minlength: this.trans('VALIDATION.FIXED_LENGTH', { length: 32 }),
        maxlength: this.trans('VALIDATION.FIXED_LENGTH', { length: 32 }),
      },
      nodeAccessKey: {
        required: this.trans('VALIDATION.REQUIRED', { name: '' }),
        pattern: this.trans('VALIDATION.PATTERN.ALPHANUMERIC_ONLY'),
        minlength: this.trans('VALIDATION.FIXED_LENGTH', { length: 16 }),
        maxlength: this.trans('VALIDATION.FIXED_LENGTH', { length: 16 }),
      },
    }
  }

  genKey(mode: AccessMode): void {
    switch (mode) {
      case AccessMode.Acquirer:
        const acquirerAccessKey = uuid()
          .replace(/-/g, '')
          .substr(0, 32)
        this.accessValidateForm.get('acquirerAccessKey').setValue(acquirerAccessKey)
        break

      case AccessMode.Node:
        const nodeAccessKey = uuid()
          .replace(/-/g, '')
          .substr(0, 16)
        this.accessValidateForm.get('nodeAccessKey').setValue(nodeAccessKey)
        break
    }
  }

  handleMerchantAccessCheck(isCheck): void {
    this.isMerchantAccess = isCheck
    if (!this.checkAccessAtLeastOne()) {
      this.msg.info(this.trans('BIZ.ACQUIRER.OTHER.TRADE.AT_LEAST_ONE_ACCESS_MODE'))
      setTimeout(() => {
        this.isMerchantAccess = true
      }, 0)
    }
  }

  handleAcquirerAccessCheck(isCheck): void {
    this.isAcquirerAccess$.next(isCheck)
    if (!this.checkAccessAtLeastOne()) {
      this.msg.info(this.trans('BIZ.ACQUIRER.OTHER.TRADE.AT_LEAST_ONE_ACCESS_MODE'))
      setTimeout(() => {
        this.isAcquirerAccess$.next(true)
      }, 0)
      return
    }
    const nodeAccessKey = this.accessValidateForm.get('nodeAccessKey').value
    if (isCheck) {
      this.isAcquirerAccessDisEditable = false
      this.accessValidateForm.reset({
        acquirerAccessKey: { value: '', disabled: false },
        nodeAccessKey: { value: nodeAccessKey, disabled: this.isNodeAccessDisEditable },
      })
    } else {
      this.accessValidateForm.reset({
        nodeAccessKey: { value: nodeAccessKey, disabled: this.isNodeAccessDisEditable },
      })
    }
  }

  handleNodeAccessCheck(isCheck): void {
    this.isNodeAccess$.next(isCheck)
    if (!this.checkAccessAtLeastOne()) {
      this.msg.info(this.trans('BIZ.ACQUIRER.OTHER.TRADE.AT_LEAST_ONE_ACCESS_MODE'))
      setTimeout(() => {
        this.isNodeAccess$.next(true)
      }, 0)
      return
    }
    const acquirerAccessKey = this.accessValidateForm.get('acquirerAccessKey').value
    if (isCheck) {
      this.isNodeAccessDisEditable = false

      this.accessValidateForm.reset({
        acquirerAccessKey: { value: acquirerAccessKey, disabled: this.isAcquirerAccessDisEditable },
        nodeAccessKey: { value: '', disabled: false },
      })
    } else {
      this.accessValidateForm.reset({
        acquirerAccessKey: { value: acquirerAccessKey, disabled: this.isAcquirerAccessDisEditable },
      })
    }
  }

  checkAccessAtLeastOne(): boolean {
    if (!this.isAcquirerAccess$.value && !this.isNodeAccess$.value && !this.isMerchantAccess) {
      return false
    }
    return true
  }

  private getAccessInfo(): Access[] {
    const accessArr: Access[] = []

    if (this.isMerchantAccess) {
      accessArr.push({ mode: AccessMode.Merchant })
    }

    const acquirerAccessKey = this.accessValidateForm.get('acquirerAccessKey').value
    const nodeAccessKey = this.accessValidateForm.get('nodeAccessKey').value

    if (acquirerAccessKey) {
      accessArr.push({ mode: AccessMode.Acquirer, key: acquirerAccessKey })
    }

    if (nodeAccessKey) {
      accessArr.push({ mode: AccessMode.Node, key: nodeAccessKey })
    }

    return accessArr
  }

  /*************************************** 商户功能 *****************************************/
  initMerFunc(): void {
    this.initValidateForm()
  }

  /* 初始化 validateForm */
  initValidateForm(): void {
    const { feature } = this.acquirer.institution.common
    this.validateForm = this.fb.group({
      multiTransCurrConfig: [feature.multiTransCurrConfig, []],
      // isSupportRisk: [feature.isSupportRisk, []],
      isSupportPostRisk: [feature.isSupportPostRisk, []],
    })
  }

  /********************************** 公共部分 ***********************************/
  checkValid(): boolean {
    this.addMinusService.validateForms.forEach(form => makeAllControlDirty(form))
    this.refreshSelRateValidate() // selRate 比较特殊，需要每次都去刷新它的校验

    const accessValid =
      (this.isAcquirerAccessDisEditable || !this.isAcquirerAccess$.value
        ? true
        : this.accessValidateForm.get('acquirerAccessKey').valid) &&
      (this.isNodeAccessDisEditable || !this.isNodeAccess$.value
        ? true
        : this.accessValidateForm.get('nodeAccessKey').valid)

    if (!this.addMinusService.valid || !accessValid) {
      this.msg.error(this.trans('GENERAL.NOTIFICATION.VALIDATION_FAIL'))
      makeAllControlDirty(this.accessValidateForm)
      return false
    }

    this.pushDataToStore()
    this.msg.success(this.trans('GENERAL.NOTIFICATION.VALIDATION_SUCCESS'))
    return true
  }

  /* 将本组件变化的数据保存到 acquirerStore */
  pushDataToStore(): void {
    const newExchangeRates = this.addMinusService.values as ExchangeRate[]
    for (const [index, rate] of newExchangeRates.entries()) {
      rate.markup = rate.markup / 100
      rate.srcCurrency = rate.srcCurrency ? rate.srcCurrency : rate.srcCurrency
      rate.dstCurrency = rate.dstCurrency ? rate.dstCurrency : rate.dstCurrency
      if (!this.chosenExchange[index]) {
        continue
      }
      const { selRate, isBest, isFixed, rateSponsor } = this.chosenExchange[index]
      if (isBest) {
        rate.isBest = true
        rate.selRate = selRate as number
      } else if (isFixed) {
        rate.isFixed = true
        rate.selRate = parseFloat(selRate as string)
      } else {
        rate.selRate = selRate as number
        rate.rateSponsor = rateSponsor
      }
    }
    this.acquirer.institution.common.tradeInfo.exchangeRates = newExchangeRates
    this.acquirer.institution.common.tradeInfo.access = this.getAccessInfo()
    this.acquirer.institution.common.feature.multiTransCurrConfig = this.validateForm.value.multiTransCurrConfig
    this.acquirer.institution.common.feature.isSupportRisk = this.validateForm.value.isSupportRisk
    this.acquirer.institution.common.feature.isSupportPostRisk = this.validateForm.value.isSupportPostRisk
    this.acquirerStore.updateValue(this.acquirer)
  }

  currencyConversionTitle(index: number): string {
    return `${this.trans('BIZ.ACQUIRER.OTHER.CURRENCY_CONVERSION')} ${index + 1}`
  }
}
